import { defineComponent, App, PropType, ref, onMounted, computed } from 'vue'
import { useNameSpace } from '../_util/hooks'
import Sunken from '../sunken'
import Icon from '../icon'

type ButtonType = 'default' | 'primary' | 'danger' | 'warning' | 'success'

const Button = defineComponent({
  name: 'x-button',
  props: {
    type: { type: String as PropType<ButtonType>, default: 'default' },
    tag: { type: String as PropType<keyof HTMLElementTagNameMap>, default: 'button' },
    dashed: Boolean,
    circle: Boolean,
    round: Boolean,
    ghost: Boolean,
    link: Boolean,
    block: Boolean,
    disabled: Boolean,
    href: String,
    target: String,
    autofocus: Boolean,
    loading: Boolean
  },
  emits: ['click'],
  directives: {
    [Sunken.name]: Sunken
  },
  setup(props, { slots, emit }) {
    const ns = useNameSpace('btn')
    const btnRef = ref<HTMLButtonElement>()

    // autofocus
    if (props.autofocus) {
      onMounted(() => {
        btnRef.value.focus()
      })
    }

    const disabledRef = computed(() => props.disabled || props.loading)

    function onClick(e) {
      // 原生 button disabled 状态仍然可以通过 Enter 触发click事件，所以这里需要判断
      if (disabledRef.value) {
        e.preventDefault()
        return
      }
      emit('click', e)
    }

    return () => {
      const { tag, loading } = props
      const disabled = disabledRef.value
      const buttonProps = {
        ref: btnRef,
        class: {
          [ns.b()]: true,
          [ns.m(props.type)]: true,
          [ns.m('dashed')]: props.dashed,
          [ns.m('circle')]: props.circle,
          [ns.m('round')]: props.round,
          [ns.m('ghost')]: props.ghost || props.dashed,
          [ns.m('link')]: props.link,
          [ns.m('block')]: props.block,
          [ns.m('disabled')]: props.disabled,
          [ns.m('only-icon')]: !slots.default
        },
        disabled,
        onClick
      }

      return (
        <tag v-sunken {...buttonProps}>
          {loading && <Icon type='loading' spin class={ns.e('icon')} />}
          {slots.default?.()}
        </tag>
      )
    }
  }
})

Button.install = (app: App) => {
  app.component(Button.name, Button)
}

export default Button
